<html lang="zh-CN">
<head>
  <meta charset="utf-8">
  <title>文档</title>
  <link href="../css/semantic/semantic.min.css" rel="stylesheet">
  <link href="../css/markdown.css" rel="stylesheet">
    <link href="../css/wtxynavigation.css" rel="stylesheet">
    <script src="../js/jquery.min.js"></script>
    <script type="text/javascript" src="../js/include.js"></script>
  <style>
    body{padding-top:0;background:#f7f7f7}
    body>.ui.container{width:100%;padding:0}
    #project-title{background:#6e6e6e;width:100%;line-height:3.572rem;color:#fff;font-size:1.2rem}
    #project-title .title-wrap{font-weight:700;padding:0 12px;width:100%;max-width:1366px!important;min-width:900px;margin:0 auto}
    #project-title .left,#project-title right{display:inline-block}
    #project-title .right{float:right}
    #project-title .right .wiki-actions .menu{left:auto;right:0;margin-top:.4em!important}
    #wiki-preview-container{width:100%;max-width:1366px!important;min-width:900px;padding:0;border:1px solid #e3e9ed;border-top:0}
    #wiki-preview>.ui.segment{margin-top:0;padding:1rem;padding-left:0;border:0}
    .hover-places{display:inline-block}
    #page-detail{width:60%;margin:0 auto}
    #page-detail .title{font-weight:700;font-size:24px;padding:12px 0;border-bottom:1px solid #ccc}
    #page-detail .content{margin-top:15px}
    .content p{word-wrap:break-word}
    #wiki-parent,#wiki-title,#wikis{display:none}
    .ui.grid{padding:0!important}
    #ex-all{cursor:pointer;color:#537c8d}
  </style>
</head>
<body>
  <div class="ui container">
    <div id="project-title">
      <div class="title-wrap">
        <div class="left">
          <i class="icon eye"></i>
          文档预览:
          mianmSDK
        </div>
        <div class="right">
          Export by Gitee
        </div>
      </div>
    </div>

    <div class="ui container" id="wiki-preview-container">
      <div id="wiki-preview">
        <div class="ui segment">
          <div id="page-detail" class="markdown-body">
            <div class='title'>21.iOS中都有哪些锁</div><div class='content'><h1>
<a id="211-ios中都有哪些锁开发中你使用过哪些锁" class="anchor" href="#211-ios%E4%B8%AD%E9%83%BD%E6%9C%89%E5%93%AA%E4%BA%9B%E9%94%81%E5%BC%80%E5%8F%91%E4%B8%AD%E4%BD%A0%E4%BD%BF%E7%94%A8%E8%BF%87%E5%93%AA%E4%BA%9B%E9%94%81"></a>21.1 iOS中都有哪些锁?(开发中你使用过哪些锁)</h1>
<p><strong>关键词</strong>:</p>
<h2>
<a id="描述" class="anchor" href="#%E6%8F%8F%E8%BF%B0"></a>描述</h2>
<h3>
<a id="1" class="anchor" href="#1"></a>1.</h3>
<h1>
<a id="答" class="anchor" href="#%E7%AD%94"></a>答:</h1>
<ol>
<li><strong>@synchronized</strong></li>
<li><strong>atomic</strong></li>
<li><strong>OSSpinLock</strong></li>
<li><strong>NSRecursiveLock</strong></li>
<li><strong>NSLock</strong></li>
<li><strong>dispatch_semaphore_t</strong></li>
</ol>
<h1>
<a id="212-这些锁怎么用的使用场景是" class="anchor" href="#212-%E8%BF%99%E4%BA%9B%E9%94%81%E6%80%8E%E4%B9%88%E7%94%A8%E7%9A%84%E4%BD%BF%E7%94%A8%E5%9C%BA%E6%99%AF%E6%98%AF"></a>21.2 这些锁怎么用的,使用场景是?</h1>
<h2>
<a id="synchronized" class="anchor" href="#synchronized"></a>@synchronized</h2>
<p><strong>一般创建单例对象的时候使用</strong></p>
<h2>
<a id="atomic" class="anchor" href="#atomic"></a>atomic</h2>
<ol>
<li><strong>首先它是修饰属性的关键字</strong></li>
<li><strong>其次是对被修饰的对象进行原子操作(不负责使用--只保证赋值线程安全)</strong></li>
</ol>
<p>不负责使用的意思如下图</p>
<p><img src="images/iOSlock01.png" alt="iOSlock01"></p>
<h2>
<a id="osspinlock" class="anchor" href="#osspinlock"></a>OSSpinLock</h2>
<ol>
<li>特点: <strong>循环等待</strong>访问, 不释放当前资源.</li>
<li>适用场景:  用于轻量级数据访问, 简单的<code>int</code>值, +1/-1操作</li>
</ol>
<p>详解见音频</p>
<h2>
<a id="nsrecursivelock-递归锁" class="anchor" href="#nsrecursivelock-%E9%80%92%E5%BD%92%E9%94%81"></a>NSRecursiveLock-递归锁</h2>
<ol>
<li><strong>递归锁可以重入</strong></li>
<li><strong>不会死锁</strong></li>
</ol>
<p>使用如下</p>
<p><img src="images/RecursiveLock.png" alt="RecursiveLock"></p>
<hr>
<h2>
<a id="nslock" class="anchor" href="#nslock"></a>NSLock</h2>
<ol>
<li>一般是用来解决一些细粒度的线程同步问题, 来保证各个线程互斥, 来进入自己的临界区</li>
<li>不可以重入</li>
</ol>
<p><strong>使用它可能会死锁</strong>, 如下
<img src="images/iOSlock02.png" alt="iOSlock02"></p>
<p>解决死锁就用, <code>NSRecursiveLock</code></p>
<h2>
<a id="dispatch_semaphore_t" class="anchor" href="#dispatch_semaphore_t"></a><code>dispatch_semaphore_t</code>
</h2>
<h3>
<a id="介绍" class="anchor" href="#%E4%BB%8B%E7%BB%8D"></a>介绍</h3>
<p><strong>信号量</strong> 也是实现线程同步的, 资源互斥的一个机制</p>
<ul>
<li>
<p><code>dispatch_semaphore_t semaphore = dispatch_semaphore_create(1);</code>:</p>
<ul>
<li>创建信号量，参数为设置信号量的初始值</li>
</ul>
</li>
<li>
<p><code>dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);</code></p>
<ul>
<li>等待信号量，第一个为当前等待的信号量，第二个参数为超时时间。当等待时间超过超时时间就不会继续等待了。</li>
</ul>
</li>
<li>
<p><code>dispatch_semaphore_signal(semaphore);</code></p>
<ul>
<li>发送当前信号量，参数为当前创建的信号量</li>
</ul>
</li>
</ul>
<p><code>dispatch_semaphore_t</code>大概长这样</p>
<pre><code>
struct semaphore {
        // 信号量的值
        int value;
        // 线程通知表, 线程唯一标识, 线程列表队列
        List &lt;thread&gt;;
};

</code></pre>
<p><code>dispatch_semaphore_wait</code>大概逻辑</p>
<pre><code>
    dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER)
    {
        semaphore.value = semaphore.value - 1;
        if (semaphore.value &lt; 0)
        {
            // 1. 小于零等于说当前线程没有资源可以访问, 我们不可获取信号量
            // 2. 于是呢当前获取信号量的线程呢, 通过一个主动的阻塞行为呢, 把自己阻塞起来
            Block(semaphore.list);
        }
    }



</code></pre>
<p><code>dispatch_semaphore_signal(semaphore);</code>大概逻辑</p>
<pre><code>
    dispatch_semaphore_signal(semaphore)
    {
        semaphore.value = semaphore.value + 1;
        if (semaphore.value &lt;= 0)
        {
            // 1. 加一之后人小于等于零, 意味着释放信号之前, 有线程在队列里面排队
            // 2. 之前如果有线程过来, 没有获取到信号量, 它们会把自己阻塞到semaphore.list这里面,
            // 3. 然后加一了还小于等于零, 就证明里面有人在排队, 那就去唤醒一个
            // 4. 唤醒操作是被动行为
            // 5. 释放线程来唤醒一个被阻塞的线程
            wakeup(semaphore.list);
        }
    }
   

</code></pre>
<h2></h2>
<hr></div>
          </div>
        </div>
      </div>
      </div>
  </div>
</body>
</html>